跳到主要内容

第一章 第1章从STC89C5RC到STM32

将STM32与前面学习的STC的51单片机进行类比学习,尤其对于已经学过51单片机的同学来说,将会更加有利于深刻理解32位单片机的用法。本章内容将STM32单片机和51单片机进行简单比较,方便读者由浅入深理解32位的单片机。

1.1历史背景

51单片机是基于Intel 8051架构,诞生于20世纪80年代,在当时的历史背景下,可以说具有划时代的意义。51单片机是单片机历史上第一款经典之作,这么多年过去了,51单片机还在被大量应用。事实上这些年8位单片机也出了不少优秀的单片机代表,但是被广泛认知的还是51单片机。因为51单片机资料很多,下载方式简单,更容易学会。 随着科技的不断发展,对单片机功能性能的需求也越来越高,传统8位单片机的资源越来越达不到更高智能化产品的需求。基于这样的市场发展,ARM公司先后推出了一系列的微处理器核ARM7、ARM9、ARM11、Cortex-M3,Cortex-M4... ...。其中在M3微处理器阶段,ST公司推出了基于M3内核的STM32F1系列的单片机。这颗单片机推出后,凭借其恰逢其时强大的功能,以及较合理的价格迅速被整个行业所认可,在整个单片机行业掀起一波流行浪潮,迅速站住了中端单片机的市场。

随着近几年国产单片机厂家的不断成长,陆续涌出与STM32类似或者兼容的单片机型号。国产单片机凭借着国家政策的支持,以及国内巨大的市场,不断压低单片机的生产成本,将原本几十块钱的32位单片机给做到了几块钱。这种情况下,32位单片机不仅仅在性能上碾压了8位的51单片机,在价格上也具备了一定竞争力。从这里也可以看出,如果还不学会32位单片机,那就有可能逐步被时代淘汰了。 由于STM32上市最早,资料最全,因此选用STM32作为32位单片机的代表芯片编写教程比较合适。学会了STM32教程,使用任何一款国产的ARM内核架构的单片机估计也不会有太多困难了。

1.2内部硬件资源比较

通过列举比较51单片机和STM32单片机的硬件资源,观察其差异。

单片机型号STC89C52RCSTM32F103VCT6
Flash大小8K256K
RAM大小0.5K48K
相关资源及寄存器数量非常多

两者的差异不仅仅是内部资源,STC89C52RC的外设接口除了串口,其他的外设接口和协议都很匮乏。而STM32支持更多的外设接口和协议,比如USB、CAN、IIC、SPI、以太网等,使得开发者能够实现更丰富的功能。用户对于单片机的认知,逐步从资源捉襟见肘的51迈入STM32的世界之后,会忽然发现,原来单片机的性能和资源这样丰富,单片机的可玩性可以达到硬件几乎不受限制,完全可以在STM32的世界里放飞自我。下面的表格为STM32F1系列单片机诸多型号的资源列表,他们之间的区别就在这张表格中,涵盖了STM32F1系列单片机从低成本到大容量的几乎所有的要求,如表1-1。  表1-1 STM32F1系列单片机资源对比

从表1-1所示可以找到教材选用的STM32F103VC,100引脚,8个16位定时器,16路12bit ADC,2路12bit DAC,80个IO口,3个SPI接口,2个I2S接口,2个I2C接口,5个UART接口,1个USB FS接口,一个CAN接口,一个SDIO接口。从表格可以看出,STM32外设丰富程度对比STC89C52完全不是一个级别。 1.3最小系统比较 单片机最小系统三要素,电源电路,晶振电路,复位电路。现在很多单片机内部集成了晶振电路和复位电路。既然内部有了,为什么还要增加外部的晶振电路或者复位电路呢? 内部RC振荡器能够在不需要任何外部器件的条件下提供系统时钟,然而,即使在校准之后他的时钟频率精度仍然较差。因此如果开发的产品对时钟频率要求比较高,那就必须得采用外部时钟;反之如果对时钟频率要求不高,就可以省掉外部的时钟电路。 外部预留复位电路通常的目的是一旦系统运行不正常,进入死机等异常状态,可以通过按下复位按键进行重启。 STC89C52单片机和STM32103单片机的最小系统电路如图1-1和图1-2所示。

图1-1 STC89C52单片机最小系统

图1-2 STM32F103单片机最小系统

1.3.1电源电路

STC89C52单片机采用5V的电源系统,STM32F103采用3.3V的电源系统,在同样工作电流的前提下,STM32的工作电压低,功率更小,更能体现低功耗环保。 从图1-1和图1-2可以看出,STM32不像51只有一组电源,而是有很多组。STM32功能更强大,内部的功能模块更多,一方面要能够给它提供足够的电流支撑单片机的正常工作,由于芯片内部走线很细,单电源不足以提供足够的电流,需要多个电源并联供电;另一方面各个模块在单片机内部分布分散,模块独立供电更有利于保持电源的稳定性,保证模块的正常工作。细心的读者会发现,电源还是成对存在的,一个VDD引脚(比如50脚)附近必然有一个对应的VSS(即GND,对应49引脚),设计线路板的时候,成对的VDD和VSS之间,在引脚附近必须加去耦电容,保证单片机的EMC特性。

1.3.2晶振电路

89C52RC单片机晶振电路采用的是11.0592M的晶振,这个晶振频率主要是为了确保串口通信波特率为整数。 STM32F103的晶振电路采用了一个8M的晶振作为STM32的主时钟源,但是不要简单的认为STM32的工作频率就是8M。STM32内部有PLL(Phase Locked Loop,即锁相环),可以起到倍频的作用,输入8M的时钟源,通过PLL可以倍频到最大72M的工作频率。 没有PLL的情况下,单片机可以通过分频电路分频降低频率。但是要提高频率,必须使用PLL实现。

1.3.3复位电路

89C52RC是个高电平复位电路,STM32F103是个低电平复位电路。 从单片机最小系统的电源电路和晶振电路,也能看出来STM32相比51复杂度要高一些,功能要强大一些。

1.4HAL库介绍

8位的51单片机开发的时候通常采用操作寄存器的方式,而随着32位单片机功能不断强大,内部特殊功能寄存器可能是巨量的,如果继续采用寄存器的方式开发,会大幅提升芯片应用门槛。因此芯片厂商为了让广大工程师用户快速使用一款芯片,会为这款芯片提供开发上的便利操作,将寄存器操作的一些程序语句封装成为函数,用户直接调用函数就可以快速完成相应操作,而这些函数就是库函数。 库函数的出现,大幅降低了用户的开发难度,有利于快速将单片机应用到实际产品当中去。ST公司陆续推出了标准库、HAL库和LL库三种版本。如果学习STM32F103VCT6这款芯片,针对这三种库函数该如何选择呢? 在ST公司的STM32Cubemx诞生之前,如果说在标准库和HAL之间选择有争议的话,那么近几年来,随着STM32CubeMX的成熟,对于技术学习和产品开发来说,采用HAL库已经毫无争议了。如果采用标准库学习,建立工程时繁琐的配置数不胜数,两天也未必成功点亮一个小灯,对于大多数初学者很有可能演变成还没入门就放弃。而采用STM32CubeMX加HAL库的学习方案,通过鼠标简单配置,十几分钟就可以完成一个简单的实验,做产品开发亦是如此,采用这种方案可以大幅提升开发效率,节省研发人员的宝贵时间。从另外一个角度讲,ST官方从STM32F4以后的单片机,不再支持和更新标准库,因此初学者完全没有必要在标准库上浪费时间,跟随本教材的STM32CubeMX加HAL库的学习方案,快速掌握实用的产品开发技能。

1.5点亮一个LED

根据开发板上的原理图,LED1、LED2、LED3和LED4这四个小灯分别接在了PD12、PD13、PD14和PD15这四个IO口上,因此如果想要点亮LED1,只需要让单片机的PD12输出一个低电平,如图1-3所示。

图1-3

图1-3

LED小灯原理图

1.5.1使用STM32CubeMX生成代码

打开STM32CubeMX,点击“ACCESS TO MCU SELECTOR”,进入“New Project from a MCU/MPU”界面,如图1-4所示。

图1-4 STM32CubeMX配置界面(一)

单击左上角“Part Number”下拉栏中,鼠标单击下拉箭头选择“STM32F103VCT6”,然后在MCUs/MPUs List选择STM32F103VCT6,如图1-5所示。

图1-5 STM32CubeMX配置界面(二)

在出现的“Pinout&Configuration”界面进行引脚配置,选择System Core菜单下的“SYS”,在Debug配置选项选择“Serial Wire”,将SWD调试接口打开,以便后续程序的下载和调试,如图1-6所示。

图1-6 STM32CubeMX引脚与配置界面(一)

选择System Core菜单下的“RCC”,将High Speed Clock(HSE)和Low Speed Clock(LSE)全部设置成为“Crystal/Ceramic Reonator”,即将时钟源设置为外部的晶振提供,相较于使用内部RC时钟,外部的时钟源提供的时钟更加精准,如图1-7所示。

图1-7 STM32CubeMX引脚与配置界面(二)

通过原理图得知,小灯LED1接到了PD12引脚上,使用鼠标左键点击右侧芯片的PD12引脚,选择“GPIO_Output”,如图1-8所示。

图1-8 STM32CubeMX引脚与配置界面(三)

选择左侧System Core菜单下的GPIO,找到刚才配置的PD12,在GPIO栏目中鼠标左键单击PD12,而后在下方User Label选项中,修改成自己想要的GPIO的命名,方便后续使用,本例程修改为LED1,如图1-9所示。

图1-9 STM32CubeMX引脚与配置界面(四)

鼠标单击“Clock Configuration”进入时钟配置界面。Kingst32开发板采用的是8M的晶振,通过STM32内部的PLL倍频后可实现最高72M的工作主频。此外,由于APB1总线时钟最大为36M,因此需要将APB1的分频器通过2分频的方式将72M分频为36M,如图1-10所示。

图1-10 STM32CubeMX时钟配置界面

鼠标单击“Project Manager”,修改项目名称,选择生成代码的路径位置,修改使用的IED工具为MDK-ARM。配置代码路径时不要使用中文字符,否则代码将丢失单片机启动文件,如图1-11所示。

图1-11 STM32CubeMX工程管理界面

鼠标单击“GENERATE CODE”按钮,可以自动生成工程以及整体的程序框架,如图1-12所示。

图1-12 STM32CubeMX代码生成界面

打开Project Manager配置的工程文件夹,可以看到STM32CubeMX将整个工程建立完毕。文件夹内有Core、Dirvers和MDK-ARM共三个文件夹,Core用来存放用户的所有代码的C源文件和H头文件;Dirver文件夹存放的是内核相关文件和HAL库的源文件;MDK-ARM文件夹存放的是工程文件,以及所有编译的过程文件和最终文件,如图1-13所示。

图1-13 STM32CubeMX代码生成界面

单击打开MDK-ARM文件夹,双击打开LED-test.uvprojx工程文件。单击编译按钮,将整个工程编译完成,可以观察到0错误0警告。单击左侧各分组的“+”号,可以看到工程包含的所有文件。双击打开main.c文件,如图1-14所示。

图1-14 源程序软件界面

从main.c文件中找到main主函数,在while(1)主循环插入下列语句,即可拉低在图1-9配置的LED1引脚,点亮LED1这颗小灯: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); 本条语句的写入做以下几点介绍: 1、工程中的代码有一部分是系统自动生成的,有一部分是作为用户编写的。为了规范期间,用户需要将代码写在/* USER CODE BEGIN*//*USER CODE END*/中间。 2、这条语句是HAL库函数,按照HAL库的手册标准格式,用户应该写成以下语句: HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);51单片机的IO口分为P0、P1、P2、P3,而STM32单片机的IO口分为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE... ...其中GPIOD代表了PD口,GPIO_PIN_12代表了第12引脚,GPIO_PIN_RESET代表了将这个引脚拉低(GPIO_PIN_SET表示拉高引脚)。而由于采用了STM32CubeMX自动生成的工程文件,在main.h文件中,为了方便和用户的配置信息进行,自动生成了宏定义,如图1-15所示。

图1-15 main.h头文件宏定义

3、采用STM32CubeMX自动生成代码后,调用库函数时用户便可以直接使用更符合用户习惯的和更直观的参数,如将“GPIOD”替换为“LED1_GPIO_Port”,将“GPIO_PIN_12”替换为“LED1_Pin”,并且完全不涉及到底层寄存器的操作了。请想一下,采用“LED1_GPIO_Port”后感官上是不是更加直观了,开发的过程更像是“计算机编程”,而不是“单片机编程”了。

1.6 DAP-LINK下载配置

使用USB线将DAP-LINK 连接到电脑上,点击“Option for Target”按钮,选择“Debug”菜单,点击“Use”选项,选择“CMSIS-DAP-Debugger”,如图1-16所示。

图1-16 选择仿真器类型

单击“Settings”选项,可以看到识别到仿真器“CMSIS-DAP_Kingst”设备,此外,也可以看到“IDCODE”值,表示仿真器和开发板连接成功,并且已经被Keil软件识别,如图1-17所示。

图1-17 仿真器连接

单击“OK”,关闭对话框。单击“编译”按钮,检查程序的语法错误。如果程序编译完成并且无错误的情况下,单击“LAOD”按钮,即可将程序下载到单片机中。按下开发板上的RST复位按键,松开手后,可以看到开发板的左下方LED1被点亮。如图1-18所示。

图1-18 点亮LE1实验

1.7课后作业

  1. 将开发板上四个LED小灯全部点亮。